package com.desay.pangoo.itmt.config;

import java.util.*;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import cn.hutool.core.bean.BeanUtil;
import com.desay.pangoo.itmt.dto.TechProjectInfoDto;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.util.HtmlUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.desay.pangoo.itmt.constants.Constant;
import com.desay.pangoo.itmt.constants.TechOnlineReviewFileds;
import com.desay.pangoo.itmt.entity.*;
import com.desay.pangoo.itmt.enums.OrgRoleEnum;
import com.desay.pangoo.itmt.feign.ProjectRequestService;
import com.desay.pangoo.itmt.repository.OrgChartRepository;
import com.desay.pangoo.itmt.repository.TechOnlineReviewRepository;
import com.desay.pangoo.itmt.repository.TechProjectInfoRepository;
import com.desay.pangoo.itmt.repository.TechRefProjectRepository;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;
import com.desay.pangoo.itmt.service.ContributionLevelService;
import com.desay.pangoo.itmt.service.LLMService;
import com.desay.pangoo.itmt.service.TechProjectInfoService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HtmlUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 定时任务
 *
 * @author uidq1163
 */
@Component
@Configuration
@EnableAsync
@Slf4j
public class TechProjectSchedule {

	@Autowired
	private TechProjectInfoRepository techProjectInfoRepository;
	@Autowired
	private TechOnlineReviewRepository techOnlineReviewRepository;
	@Autowired
	private OrgChartRepository orgChartRepository;
	@Autowired
	private MailSenderService mailSenderService;
	@Autowired
	private TechRefProjectRepository techRefProjectRepository;
	@Autowired
	private ProjectRequestService projectRequestService;
	@Autowired
	private ContributionLevelService contributionLevelService;
	@Autowired
	private TechProjectInfoService techProjectInfoService;
	@Autowired
	private LLMService llmService;
	@Value("${itmt.project.url}")
	private String projectPreUrl;
	@Value("${spring.profiles.active}")
	private String active;

	/**
	 * 每周一早上8点：检查是否有超过计划：还是为plan状态的项目，通知到14个工作组负责人
	 *
	 * @throws InterruptedException
	 */
	@Scheduled(cron = "0 0 8 ? * MON")
	public void dueDateProjectPushMail() {
		// 判断运行环境是否为prod
		if (StringUtils.equals(active, "dev")) {
			return;
		}
		log.info("定时任务开始执行");
		List<Long> projectIds = techProjectInfoRepository.getAllDueDateProjectIds();
		if (CollUtil.isNotEmpty(projectIds)) {
			Iterable<TechProjectInfoEntity> techProjectInfoList = techProjectInfoRepository.findAllById(projectIds);
			Iterator<TechProjectInfoEntity> it = techProjectInfoList.iterator();
			List<String[]> contentList = new ArrayList<>();
			contentList.add(new String[] { "序号", "工作组", "项目名称", "项目编号", "操作" });
			int index = 1;
			while (it.hasNext()) {
				TechProjectInfoEntity techProjectInfoEntity = it.next();
				WorkGroupEntity workGroup = techProjectInfoEntity.getTechClass().getWorkGroup();
				Long workGroupId = workGroup.getId();
				Long projectId = techProjectInfoEntity.getId();
				JSONObject jSONObject;
				String techName = techProjectInfoEntity.getTechName();
				try {
					jSONObject = JSON.parseObject(techName);
					if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
							&& null != jSONObject.getString(Constant.JSON_STR)) {
						techName = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				String url = host + "/" + projectPreUrl + "?workGroupId=" + workGroupId + "&projectId=" + projectId;
				url = "<a href=" + url + ">查看</a>";
				contentList.add(new String[] { "" + index, workGroup.getWorkGroupName(), techName,
						techProjectInfoEntity.getTechPtn(), url });
				index++;
			}
			String title = "ITMT技术RoadMap逾期提醒";
			List<String> userMails = getUserGroupEmailInfo(TechOnlineReviewSchedule.ITMT_LEADER);
			HtmlTableTemplate template = new HtmlTableTemplate();
			String content = template.generateHtml(contentList);
			mailSenderService.sendMail(title, content, userMails.toArray(new String[userMails.size()]), cc);
		}
	}

	@Value("${itmt.host}")
	private String host;

	@Value("${itmt.leaders.mail.cc}")
	private String[] cc;

	public List<String> getUserGroupEmailInfo(String groupName) {
		List<OrgChartEntity> listObject = null;
		if (groupName.equals(TechOnlineReviewSchedule.ITMT_LEADER)) {
			listObject = orgChartRepository.findByOrgRole(2);
		} else if (groupName.equals(TechOnlineReviewSchedule.ITMT_SUB_LEADER)) {
			listObject = orgChartRepository.findByOrgRole(3);
		}
		// 组织角色:ITMT ChairMan:1，ITMT Leader:2，ITMT SubLeader:3，ITMT成员:4，TSP:5
		return listObject == null ? new ArrayList<>()
				: listObject.stream().filter(f -> null != f.getEmail()).map(m -> m.getEmail()).toList();
	}

	/**
	 * 增加【技术交付评审】，系统根据技术交付评审结论，自动调整字段内容为【Success】【Failure】， 未评审则为【-】，BU需求则为【BU's
	 * NEEDS】
	 */
	@Scheduled(cron = "0 0/5 * * * ?")
	public void dueDateOnLineReview() {
		ExpandCriteria<TechOnlineReviewEntity> c = new ExpandCriteria<>();
		// 技术成果交付评审
		c.add(Restrictions.eq(TechOnlineReviewFileds.REVIEWTYPE, 3, true));
		// 没有反馈结果
		c.add(Restrictions.isNotNull(TechOnlineReviewFileds.REVIEWRESULT));
		// 关联了技术课题
		c.add(Restrictions.isNotEmpty("techProjects"));
		c.add(Restrictions.or(Restrictions.eq("techProjects.deliveryReview", "Failure", true),
				Restrictions.eq("techProjects.deliveryReview", "-", true)));
		List<TechOnlineReviewEntity> listExist = techOnlineReviewRepository.findAll(c);
		listExist.stream().forEach(item -> {
			Set<TechProjectInfoEntity> projects = item.getTechProjects();
			projects.forEach(project -> {
				Optional<TechProjectInfoEntity> option = techProjectInfoRepository.findById(project.getId());
				TechProjectInfoEntity tempProject = option.get();
				if (tempProject.getDeliveryReview().equals("-") || tempProject.getDeliveryReview().equals("Failure")) {
					if (item.getReviewResult()) {
						tempProject.setDeliveryReview("Success");
					} else {
						tempProject.setDeliveryReview("Failure");
					}
					techProjectInfoRepository.save(tempProject);
				}
			});
		});
	}

	/**
	 * 每天晚上1点执行一次，同步项目信息 需求方说暂时不需要同步
	 */
	@Scheduled(cron = "0 0 1 * * ?")
	public void updateTrinityProject() {
		ExpandCriteria<ProjectEntity> c = new ExpandCriteria<>();
		List<ProjectEntity> listExist = techRefProjectRepository.findAll(c);
		listExist.stream().forEach(item -> {
			if (StringUtils.isEmpty(item.getProjectName())) {
				return;
			}
			ResponseEntity<HashMap<String, String>> response = projectRequestService
					.getProjectInfo(item.getProjectName());
			HashMap<String, String> projectDto = response.getBody();
			if (null == projectDto) {
				log.error("项目信息不存在--{}", item.getProjectName());
			} else {
				// 【项目编号】
				item.setProjectNo(projectDto.get("almProjectId"));
				// 【项目结果】
				item.setProjectResult(projectDto.get("finalResult"));
				// 【立项时间】
				item.setApprovalDate(projectDto.get("actualStartDate"));
				// 【实际结项时间】
				item.setActualClosedDate(projectDto.get("actualEndDate"));
				// 【预计结项时间】
				item.setEstimateClosedDate(projectDto.get("estimatedEndDate"));
				techRefProjectRepository.save(item);
			}
		});
	}

	// 每个月1号计算上个月的贡献度
	@Scheduled(cron = "0 0 0 1 * *")
	public void calContributionLevel() {
		// 获取当前日期
		DateTime date = DateUtil.date();
		DateTime beginDate = date.offset(DateField.MONTH, -1);
		contributionLevelService.calContributionPreMonth(beginDate);
	}

	// 每天晚上23:50:30秒执行
	@Scheduled(cron = "30 50 23 * * *")
	public void sendTechProjectInfoToAi() {
		// 获取当天的日期
		Date now = new Date();
		// 获取当天以及昨天的技术提案
		List<TechProjectInfoEntity> techProjectInfoEntityList = techProjectInfoService.listTechProjectInfoInDate(now);
		// 将提案发送给算法端
		// 发送给算法端
		Boolean res = llmService.sendTechProject(techProjectInfoEntityList);
		// 判断发送的状态并记录日志
		if (!res) {
			List<String> list = techProjectInfoEntityList.stream().map(TechProjectInfoEntity::getTechPtn).toList();
			log.warn("send tech project info fail: ptns: {} ", list);
		}
	}

	static class HtmlTableTemplate {

		/**
		 * 生成html内容
		 *
		 * @param contentList
		 *            写入表格的内容，第一行作为表头
		 * @return
		 */
		public String generateHtml(List<String[]> contentList) {
			StringBuilder stb = new StringBuilder();
			stb.append("<!DOCTYPE html>\n").append("<html lang=\"zh\">\n").append(this.generateHtmlHead())
					.append(this.generateHtmlBody(contentList)).append("</html>");
			return stb.toString();
		}

		/**
		 * 生成html head标签里面的内容
		 *
		 * @return
		 */
		public String generateHtmlHead() {
			return """
					<head>
					    <meta charset="UTF-8">
					    <title>title</title>
					    <meta name="description" content="html table">
					 </head>
					""";
		}

		/**
		 * 生成body标签里面的内容
		 *
		 * @param contentList
		 *            第一行数据默认作为表头字段
		 * @return
		 */
		public String generateHtmlBody(List<String[]> contentList) {
			StringBuilder stb = new StringBuilder();
			stb.append("<body>\n").append("<p>Dears ITMT成员：</p>")
					// 指定样式
					.append("<table style=\"border-width: 1px;border-collapse: collapse;margin: 0 auto;width: 100%;\">\n");
			for (int i = 0; i < contentList.size(); i++) {
				if (i == 0) {
					// 生成表头
					stb.append("    <tr>\n");
					String[] tableHead = contentList.get(0);
					for (int j = 0; j < tableHead.length; j++) {
						stb.append(
								"        <th style=\"border-width:1px;padding:8px;border-style:solid;background-color:#dedede;\">")
								.append(tableHead[j]).append("</th>\n");
					}
					stb.append("    </tr>\n");
				} else {
					// 生成数据
					stb.append("    <tr>\n");
					String[] tableData = contentList.get(i);
					for (int j = 0; j < tableData.length; j++) {
						stb.append("        <td style=\"border-width:1px;padding:8px;border-style:solid;\">")
								.append(tableData[j]).append("</td>\n");
					}
					stb.append("    </tr>\n");
				}
			}
			stb.append("</table>\n");
			stb.append("<p style='color:red'>以上技术RoadMap已经逾期待处理</p>");
			stb.append("<p>请及时跟踪技术RoadMap状态。</p>");
			stb.append("<p>谢谢！</p><h2>*&nbsp;本邮件由ITMT系统自动发送</h2>");
			stb.append("</body>");
			return stb.toString();
		}
	}

	/**
	 * 检查技术课题是否有必填字段没有填写的，发邮件通知对应的leader
	 */
	@Scheduled(cron = "0 0 8 ? * MON")
	public void checkProjectInfoPushMail() {
		// 判断运行环境是否为prod
		if (StringUtils.equals(active, "dev")) {
			return;
		}
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		Validator validator = factory.getValidator();
		Iterable<TechProjectInfoEntity> list = techProjectInfoRepository.findAll();
		List<TechProjectInfoEntity> noticeTechProjectList = new ArrayList<>();
		for (TechProjectInfoEntity projectInfo : list) {
			TechProjectInfoDto dto = new TechProjectInfoDto();
			BeanUtil.copyProperties(projectInfo, dto);
			Set<ConstraintViolation<TechProjectInfoDto>> violations = validator.validate(dto);
			if (!violations.isEmpty()) {
				noticeTechProjectList.add(projectInfo);
			}
		}
		if (noticeTechProjectList.isEmpty()) {
			return;
		}
		// noticeTechProjectList按照工作组分组，把每个工作组的邮件内容发送给对应的leader
		Map<WorkGroupEntity, List<TechProjectInfoEntity>> groupByWorkGroup = noticeTechProjectList.stream().collect(
				Collectors.groupingBy(techProjectInfoEntity -> techProjectInfoEntity.getTechClass().getWorkGroup()));
		for (Map.Entry<WorkGroupEntity, List<TechProjectInfoEntity>> entry : groupByWorkGroup.entrySet()) {
			WorkGroupEntity workGroup = entry.getKey();
			List<TechProjectInfoEntity> techProjectInfos = entry.getValue();
			List<String[]> contentList = constructEmailContent(workGroup, techProjectInfos);
			String title = "ITMT技术RoadMap信息不完整";
			OrgChartEntity orgChartLeader = orgChartRepository.findByWorkGroupAndOrgRole(workGroup,
					OrgRoleEnum.ITMT_Leader.getValue());
			HtmlTableTemplate template = new HtmlTableTemplate();
			String content = template.generateHtml(contentList);
			mailSenderService.sendMail(title, content, new String[] { orgChartLeader.getEmail() }, null);
		}
	}

	/**
	 * 构造邮件内容
	 * 
	 * @param workGroup
	 * @param techProjectInfos
	 * @return
	 */
	private List<String[]> constructEmailContent(WorkGroupEntity workGroup,
			List<TechProjectInfoEntity> techProjectInfos) {
		List<String[]> contentList = new ArrayList<>();
		contentList.add(new String[] { "序号", "工作组", "项目名称", "项目编号", "操作" });
		int index = 1;
		Long workGroupId = workGroup.getId();
		for (TechProjectInfoEntity techProjectInfo : techProjectInfos) {
			Long projectId = techProjectInfo.getId();
			String techName = sanitizeTechName(techProjectInfo.getTechName());
			String url = String.format("<a href='%s/%s?workGroupId=%s&projectId=%s'>查看</a>", host, projectPreUrl,
					workGroupId, projectId);
			contentList.add(new String[] { "" + index, workGroup.getWorkGroupName(), techName,
					techProjectInfo.getTechPtn(), url });
			index++;
		}
		return contentList;

	}

	private String sanitizeTechName(String techName) {
		JSONObject jSONObject;
		try {
			jSONObject = JSON.parseObject(techName);
			if (jSONObject != null && jSONObject.containsKey(Constant.JSON_STR)
					&& jSONObject.getString(Constant.JSON_STR) != null) {
				return HtmlUtils.htmlEscape(jSONObject.getString(Constant.JSON_STR)); // 防止HTML标签注入
			}
		} catch (Exception e) {
			// 合适的异常处理逻辑
			e.printStackTrace();
		}
		return techName; // 如果无法解析或异常发生，保持原始字符串
	}
}
